# Virtual Router Simulator 
#
# Copyright (C) 2009-2010 VRSim Project
# Author: Choonho Son <choonho@kt.com>
# URL: <http://vrsim.googlecode.com>
# For license information, see LICENSE.TXT
#

from PyQt4 import QtGui,  QtCore

import VRSim.Globals as globals
from VRSim.Node.Juniper_M40 import Juniper_M40
from VRSim.Node.Cisco_C7200 import Cisco_C7200
from VRSim.Node.Router import Router
from VRSim.Node.Server import Server
from VRSim.Node.DHCP import DHCP
from VRSim.Node.Linux import Linux
from VRSim.Node.WindowsXP import WindowsXP
from VRSim.Node.Host import Host
from VRSim.Node.PhysNode import PhysNode
from VRSim.Link.Ethernet import Ethernet
from VRSim.Utils import debug,  message

from VRSim.Ui.Ui_LinkConnection import Ui_LinkConnection

class LinkConnection(QtGui.QDialog,  Ui_LinkConnection):
    def __init__(self,  link):
        QtGui.QDialog.__init__(self)
        Ui_LinkConnection.__init__(self)
        self.setupUi(self)
        
        # saving flag
        self.isSaved = True
        self.link = link
        self.linktype = link.type
        srcid = link.source.nodeid
        dstid = link.dest.nodeid
        self.srcnode = globals.GApp.topology.nodes[srcid].physnode
        self.dstnode = globals.GApp.topology.nodes[dstid].physnode
        self.slotAAdapter = None
        self.slotBAdapter = None
        
        self.connect(self.buttonBox,  QtCore.SIGNAL('accepted()'),  self.__save )
        self.connect(self.buttonBox,  QtCore.SIGNAL('rejected()'),  self.close )
        
        tf = self.initialize()
        if tf == False:
            # initialization failed
            debug("self.close()")
            self.isSaved = False
            #QtGui.QDialog.close(self)
            self.buttonBox.emit(QtCore.SIGNAL('rejected()'))
            
            
        
        else:    
            self.connect(self.comboBox_slotA,  QtCore.SIGNAL("currentIndexChanged(int)"),  self.__updatePortA )
            self.connect(self.comboBox_slotB,  QtCore.SIGNAL("currentIndexChanged(int)"),  self.__updatePortB )
        
        
        
            
    def initialize(self):
        """ fill combo menu
        """
        self.label_routerA.setText(self.srcnode.hostname)
        self.label_routerB.setText(self.dstnode.hostname)
        
        self.srcslot = self.updateSlotNPort(self.srcnode,  self.comboBox_slotA,  self.comboBox_portA)
        print "srslot :",  self.srcslot
        if self.srcslot == False:
            return False
        self.dstslot = self.updateSlotNPort(self.dstnode,  self.comboBox_slotB,  self.comboBox_portB)
        print "dstslot :",  self.dstslot
        if self.dstslot == False:
            return False
        
            
    #################
    # slot
    #################
    def __updatePortA(self):
        # update port by slot change
        new_port = self.srcslot[str(self.comboBox_slotA.currentText())]
        self.comboBox_portA.clear()
        for item in new_port:
            self.comboBox_portA.addItem(item)
                
    def __updatePortB(self):
        # update port by slot change
        new_port = self.dstslot[str(self.comboBox_slotB.currentText())]
        self.comboBox_portB.clear()
        for item in new_port:
            self.comboBox_portB.addItem(item)
    
    def parseSlot(self,  str):
        """ parse slot string
        ex) slot 0, slot 2
        """
        item = str.split(" ")
        return int(item[1])
        
    def parsePort(self,  str):
        """ parse port string
        ex) FastEthernet 0/0, fxp 0, em 0
        """
        # parse space
        item = str.split(" ")
        # parse "/"
        portItem = item[1].split("/")
        if len(portItem) == 1:
            """ PC style ex) fxp 0
            """
            #return int(portItem[0])
            # there is no port number (always 0)
            return 0
            
        elif len(portItem) == 2:
            """ cisco style ex) 1/1
            """
            return int(portItem[1])
        else:
            msg = "Unknown Interface Name: %s",  str
            debug(msg)
        
        
    def __save(self):
        # currentIndex isnot slot or port number
        # parse text
        # update Ethernet information
        """
        slotAIndex = self.comboBox_slotA.currentIndex()
        slotBIndex = self.comboBox_slotB.currentIndex()
        portAIndex = self.comboBox_portA.currentIndex()
        portBIndex = self.comboBox_portB.currentIndex()
        """
        slotAIndex = self.parseSlot(self.comboBox_slotA.currentText())
        slotBIndex = self.parseSlot(self.comboBox_slotB.currentText())
        portAIndex = self.parsePort(self.comboBox_portA.currentText())
        portBIndex = self.parsePort(self.comboBox_portB.currentText())
        
        # TODO: check slot&port is already assigned?
        AisAssigned = self.srcnode.devices.isAssigned(slotAIndex,  portAIndex)
        BisAssigned = self.dstnode.devices.isAssigned(slotBIndex,  portBIndex)
        ret = True
        if AisAssigned == True:
            output = "( Slot " + str(slotAIndex) + " : Port " + str(portAIndex) + " ) of " + str(self.srcnode.hostname) + " is already used"
            ret = message(output,  "critical")
        if BisAssigned == True:
            output = self.dstnode.hostname + " of "
            output = "( Slot " + str(slotBIndex) + " : Port " + str(portBIndex) + " ) of " + str(self.dstnode.hostname) + "is already used"
            ret = message(output,  "critical")
        
        if ret == False:
            debug("exit")
            self.isSaved = False
            return False        
        
        self.link.srcIf = self.comboBox_portA.currentText()
        self.link.destIf = self.comboBox_portB.currentText()
        self.link.delay = self.lineEdit_delay.text()
        self.link.updateLabel()
        
        # update Domain NIC information
        self.srcnode.devices.updateNic(slotAIndex, portAIndex,   self.link.srcIfPort,  self.link.destIfPort,  self.link.delay)
        self.dstnode.devices.updateNic(slotBIndex,  portBIndex,  self.link.destIfPort,  self.link.srcIfPort,  self.link.delay)
        
        self.close()
    
    # slot, port are QT4 GUI object
    def updateSlotNPort(self,  pnode,  slot,  port):
        """ update unused interfaces by linktype
        """
        self.unusedIfs = pnode.devices.getUnusedInterfaces(self.linktype)
        if self.unusedIfs == False:
            # there is no data!
            return False
            
        slots = self.unusedIfs.keys()
        slots.sort()
        # clear slot
        slot.clear()
        for slotName in slots:
            slot.addItem(slotName)
        
        # update port by slot
        selSlot = str(slot.currentText())
        for item in self.unusedIfs[selSlot]:
                port.addItem(item)
           
        return self.unusedIfs
        """
        if isinstance(pnode,  PhysNode):
            # Juniper Router
            # Max interface: 8
            # linktype check
                  
            # Ethernet
            if self.linktype == globals.Enum.LinkType.Ethernet and isinstance(pnode,  Juniper_M40):
                curent_slot = globals.qemu_ethernet_slot
            elif self.linktype == globals.Enum.LinkType.Ethernet and isinstance(pnode,  Cisco_C7200):
                curent_slot  = globals.cisco_ethernet_slot                
            # FastEthernet
            elif self.linktype == globals.Enum.LinkType.FastEthernet and isinstance(pnode,  Juniper_M40):
                curent_slot = globals.qemu_fastethernet_slot
            elif self.linktype == globals.Enum.LinkType.FastEthernet and isinstance(pnode,  Linux):
                curent_slot = globals.qemu_fastethernet_slot
            elif self.linktype == globals.Enum.LinkType.FastEthernet and isinstance(pnode,  WindowsXP):
                curent_slot = globals.qemu_window_slot
            elif self.linktype == globals.Enum.LinkType.FastEthernet and isinstance(pnode,  Cisco_C7200):
                curent_slot = globals.cisco_fastethernet_slot
            # GigaEthernet
            elif self.linktype == globals.Enum.LinkType.GigaEthernet and isinstance(pnode,  Juniper_M40):
                curent_slot = globals.qemu_gigaethernet_slot
            elif self.linktype == globals.Enum.LinkType.GigaEthernet and isinstance(pnode,  Cisco_C7200):
                curent_slot = globals.cisco_gigaethernet_slot
            elif self.linktype == globals.Enum.LinkType.GigaEthernet and isinstance(pnode,  WindowsXP):
                curent_slot = globals.qemu_window_slot
            elif self.linktype == globals.Enum.LinkType.Ethernet and isinstance(pnode,  WindowsXP):
                curent_slot = globals.qemu_window_slot
            
            else:
                debug("Unknown Link Type")
                curent_slot = []
            
            # get blank slot, port
            (slotN, portN) = pnode.devices.getBlankSlotNPort(self.link.typeName)
            keys = curent_slot.keys()
            keys.sort()
            # TODO: proper seletected item
            # find blank slot 
            for item in keys:
                slot.addItem(item)
            slot.setCurrentIndex(slotN)
            
            # update port by slot
            # TODO: proper port name
            selSlot = str(slot.currentText())
            for item in curent_slot[selSlot]:
                port.addItem(item)
            port.setCurrentIndex(portN)
                
            
            return curent_slot
        """
